package cn.paraview.mfa.http;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Map;

import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.httpclient.methods.multipart.StringPart;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.httpclient.protocol.Protocol;

import android.text.TextUtils;
import cn.paraview.mfa.AppContext;
import cn.paraview.mfa.URLs;
import cn.paraview.mfa.entity.MySSLProtocolSocketFactory;

public class HttpRequest {

	public static final String UTF_8 = "UTF-8";
	private static String appUserAgent = "";
	private static String tokenStr = "";

	private final static int TIMEOUT_CONNECTION = 10000;
	private final static int TIMEOUT_SOCKET = 20000;
	private final static int RETRY_TIME = 2;

	private static HttpClient httpClient = null;

	private static String getUserAgent() {
		if (!TextUtils.isEmpty(appUserAgent)) {
			StringBuilder ua = new StringBuilder("ECPMobile");
			ua.append("/" + android.os.Build.VERSION.RELEASE);// 手机系统版本
			ua.append("/" + android.os.Build.MODEL); // 手机型号
			appUserAgent = ua.toString();
		}
		return appUserAgent;
	}

	public static HttpClient getHttpClient() {
		if (httpClient == null) {
			httpClient = new HttpClient();
			// 设置 HttpClient 接收 Cookie,用与浏览器一样的策略
			httpClient.getParams().setCookiePolicy(
					CookiePolicy.BROWSER_COMPATIBILITY);
			// 设置 默认的超时重试处理策略
			httpClient.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
					new DefaultHttpMethodRetryHandler());
			// 设置 连接超时时间
			httpClient.getHttpConnectionManager().getParams()
			.setConnectionTimeout(TIMEOUT_CONNECTION);
			// 设置 读数据超时时间
			httpClient.getHttpConnectionManager().getParams()
			.setSoTimeout(TIMEOUT_SOCKET);
			// 设置 字符集
			httpClient.getParams().setContentCharset(UTF_8);
			Protocol myhttps = new Protocol("https", new MySSLProtocolSocketFactory(), 443);   
			Protocol.registerProtocol("https", myhttps);
		}
		return httpClient;
	}

	private static PostMethod getHttpPost(String url, String cookie,
			String userAgent) {
		PostMethod httpPost = new PostMethod(url);
		// 设置 请求超时时间
		httpPost.getParams().setSoTimeout(TIMEOUT_SOCKET);
		httpPost.setRequestHeader("Host", URLs.HOST);
		httpPost.setRequestHeader("Connection", "Keep-Alive");
		// httpPost.setRequestHeader("Cookie", cookie);
		httpPost.setRequestHeader("User-Agent", userAgent);
		if (!TextUtils.isEmpty(tokenStr)) {
			httpPost.setRequestHeader("access_token", tokenStr);
		}
		return httpPost;
	}

	public static String http_post(String url, Map<String, Object> params,
			Map<String, File> files, Map<String, String> headerParams){
		String userAgent = getUserAgent();
		HttpClient httpClient = null;
		PostMethod httpPost = null;

		// post表单参数处理
		int length = (params == null ? 0 : params.size()) + (files == null ? 0 : files.size());
		Part[] parts = new Part[length];
		int i = 0;
		if (params != null)
			for (String name : params.keySet()) {
				parts[i++] = new StringPart(name, String.valueOf(params.get(name)), UTF_8);
			}
		if (files != null)
			for (String file : files.keySet()) {
				try {
					parts[i++] = new FilePart(file, files.get(file));
				} catch (FileNotFoundException e) {
					e.printStackTrace();
				}
			}

		String responseBody = "";
		int time = 0;
		do {
			try {
				httpClient = getHttpClient();
				httpPost = getHttpPost(url, null, userAgent);
				httpPost.setRequestEntity(new MultipartRequestEntity(parts,httpPost.getParams()));
				if (headerParams != null) {
					for (String headerStr : headerParams.keySet()) {
						httpPost.setRequestHeader(headerStr,
								headerParams.get(headerStr));
					}
				}
				int statusCode = httpClient.executeMethod(httpPost);
				if (statusCode == HttpStatus.SC_OK){
					responseBody = httpPost.getResponseBodyAsString();
				}
				break;
			} catch (Exception e) {
				time++;
				if (time < RETRY_TIME) {
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e1) {
					}
					continue;
				}
				e.printStackTrace();
			} finally {
				httpPost.releaseConnection();
			}
		} while (time < RETRY_TIME);
		responseBody = responseBody.replaceAll("\\p{Cntrl}", "");
		return responseBody;
	}
	
	private static GetMethod getHttpGet(String url, String cookie,
			String userAgent) {
		GetMethod httpGet = new GetMethod(url);
		// 设置 请求超时时间
		httpGet.getParams().setSoTimeout(TIMEOUT_SOCKET);
		httpGet.setRequestHeader("Host", URLs.HOST);
		httpGet.setRequestHeader("Connection", "Keep-Alive");
		// httpGet.setRequestHeader("Cookie", cookie);
		httpGet.setRequestHeader("User-Agent", userAgent);
		return httpGet;
	}
	
	public static String http_get(AppContext appContext, String url){
		String userAgent = getUserAgent();

		HttpClient httpClient = null;
		GetMethod httpGet = null;

		String responseBody = "";
		int time = 0;
		do {
			try {
				httpClient = getHttpClient();
				httpGet = getHttpGet(url, null, userAgent);
				int statusCode = httpClient.executeMethod(httpGet);
				if (statusCode == HttpStatus.SC_OK) {
					responseBody = httpGet.getResponseBodyAsString();
				}
				break;
			} catch (Exception e) {
				time++;
				if (time < RETRY_TIME) {
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e1) {
					}
					continue;
				}
				e.printStackTrace();
			} finally {
				httpGet.releaseConnection();
			}
		} while (time < RETRY_TIME);
		responseBody = responseBody.replaceAll("\\p{Cntrl}", "");
		return responseBody;
	}
}
